package com.acme.bankapp.apps;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

import com.acme.bankapp.domain.BankService;
import com.acme.bankapp.domain.ClientExistsException;
import com.acme.bankapp.domain.Gender;
import com.acme.bankapp.services.DataWorker;

public class ServerApplication {

	private final int port;

	public static final String INITIAL_MESSAGE = "enter command";
	public static final String ADD_CLIENT_MESSAGE_HEADER = "addclient";
	public static final String GET_CLIENTS_MESSAGE_HEADER = "getclients";
	public static final String END_SESSION_MESSAGE = "end";

	private BankService bankService;

	public ServerApplication(int port) {
		this.port = port;
	}

	public void start(String bankSerialization) {

		bankService = new BankService();
		try {
			bankService.setDataWorker(new DataWorker(bankSerialization));
		} catch (FileNotFoundException e1) {
			System.err.println("Error creating serialization bank");
			e1.printStackTrace();
			return;
		}
		try {
			bankService.loadBank();
		} catch (IOException e) {
			System.err.println("Error restoring serialization bank");
			e.printStackTrace();
			return;
		}

		System.out.println("Server started");

		while (true) {
			try (ServerSocket serverSocket = new ServerSocket(port);
					Socket clientSocket = serverSocket.accept();
					PrintWriter out = new PrintWriter(
							clientSocket.getOutputStream(), true);
					BufferedReader in = new BufferedReader(
							new InputStreamReader(clientSocket.getInputStream()));) {

				String inputLine;
				String outputLine;

				out.println(INITIAL_MESSAGE);

				while ((inputLine = in.readLine()) != null) {
					System.out.println("Client: " + inputLine);
					if (inputLine.equals(END_SESSION_MESSAGE)){
						System.out.println("client disconnected, waiting for new one");
						break;
					}
					outputLine = processMessage(inputLine);
					out.println(outputLine);
				}
			} catch (IOException e) {
				System.err
						.println("Exception caught when trying to listen on port "
								+ port + " or listening for a connection");
				System.out.println("client disconnected, waiting for new one");
			}
		}

		// serverSocket.close();
	}

	private String processMessage(String message) {
		if (message.startsWith(ADD_CLIENT_MESSAGE_HEADER)) {
			return addClient(message.substring(ADD_CLIENT_MESSAGE_HEADER
					.length()));
		} else if (message.startsWith(GET_CLIENTS_MESSAGE_HEADER)) {
			return getClientList();
		}

		return "No such command";
	}

	private String addClient(String addClientString) {
		String[] clientInfo = addClientString.split(":");
		try {
			bankService.addClient(bankService.createClient(clientInfo[0],
					"m".equals(clientInfo[1]) ? Gender.MALE : Gender.FEMALE));
			return "client added";
		} catch (ClientExistsException e) {
			System.err.println(e.getMessage());
			return "error happened";
		}
	}

	private String getClientList() {
		return bankService.reportBankClients().replace("\n", "\\n");
	}

}
